package com.aaron.messenger.net;

import java.io.IOException;
import java.io.StringReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import com.aaron.messenger.data.AudioRequest;
import com.aaron.messenger.data.ChatMessage;
import com.aaron.messenger.data.UdpPacket;
import com.aaron.messenger.data.VideoRequest;

/**
 * <message>
 * <cmd>chat</cmd>
 * <from>*.*.*.*</from>
 * <to>*.*.*.*</to>
 * <id>*</id>
 * <packetnum>*</packetnum>
 * <subid>*</subid>
 * <data>***</data>
 * <img>***</img>
 * </message>
 * 
 * <message>
 * <cmd>audio</cmd>
 * <from>*.*.*.*</from>
 * <to>*.*.*.*</to>
 * </message>
 * 
 * 
 * <message>
 * <cmd>video</cmd>
 * <from>*.*.*.*</from>
 * <to>*.*.*.*</to>
 * </message>
 * 
 * 
 * */

public class UdpReceiver extends Thread {
	public interface ChatDataReceivedListener {
		public void OnChatDataReceived(ChatMessage msg);
	}
	
	public interface AudioChatRequestListener {
		public void OnAudioChatRequest(AudioRequest request);
	}
	
	public interface VideoChatRequestListener {
		public void OnVideoChatRequest(VideoRequest request);
	}
	
	DatagramSocket mReceiverSocket;
	ChatDataReceivedListener mChatListener;
	AudioChatRequestListener mAudioListener;
	VideoChatRequestListener mVideoListener;
	XmlPullParser mParser;
	
	public UdpReceiver(String name) {
		super(name);
	}
	
	public void setChatListener(ChatDataReceivedListener listener) {
		mChatListener = listener;
	}
	
	public void setAudioRequestListener(AudioChatRequestListener listener) {
		mAudioListener = listener;
	}
	
	public void setVideoRequestListener(VideoChatRequestListener listener) {
		mVideoListener = listener;
	}
	
	public void stopReceive() {
		if(mReceiverSocket != null) {
			mChatListener = null;
			mAudioListener = null;
			mVideoListener = null;
			mReceiverSocket.close();
		}
	}
	
	public void run() {
		try {
			mReceiverSocket = new DatagramSocket(NetPort.UDP_CHAT_PORT);
			XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
			mParser = factory.newPullParser();
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (XmlPullParserException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		while(true) {
			byte[] data = new byte[1024]; 
			DatagramPacket pack = new DatagramPacket(data, 1024);
			try {
				mReceiverSocket.receive(pack);
				parserPacket(data, pack.getLength());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				if(!mReceiverSocket.isClosed()) {
					mReceiverSocket.close();
				}
				mReceiverSocket = null;
				return;
			}
		}
	}
	
	private void parserPacket(byte[] data, int length) {
		String info = new String(data, 0,length);
		UdpPacket udp = null;
		int type = -1;
		String tagName = null;
		try {
			mParser.setInput(new StringReader(info));
			int eventType = mParser.getEventType();
			while(eventType != XmlPullParser.END_DOCUMENT) {
				switch(eventType) {
				case XmlPullParser.START_DOCUMENT:
					break;
				case XmlPullParser.START_TAG:
					tagName = mParser.getName();
					break;
				case XmlPullParser.END_TAG:
					break;
				case XmlPullParser.TEXT:
					String text = mParser.getText();
					if(tagName.equals("cmd")) {
						if(text.equals("chat")) {
							type = 0;
							udp = new ChatMessage();
						} else if(text.equals("audio")) {
							type = 1;
							udp = new AudioRequest();
						} else if(text.equals("video")) {
							type = 2;
							udp = new VideoRequest();
						} 
					}
					if(tagName.equals("from")) {
						udp.setSource(text);
					}
					if(tagName.equals("to")) {
						udp.setTarget(text);
					}
					if(tagName.equals("data")) {
						((ChatMessage)udp).appendData(text, ChatMessage.TYPE_STRING);
					}
					if(tagName.equals("img")) {
						((ChatMessage)udp).appendData(text, ChatMessage.TYPE_IMAGE);
					}
					if(tagName.equals("id")) {
						((ChatMessage)udp).setId(Long.parseLong(text));
					}
					if(tagName.equals("packetnum")) {
						((ChatMessage)udp).setPacketNum(Integer.parseInt(text));
					}
					if(tagName.equals("subid")) {
						((ChatMessage)udp).setSubId(Integer.parseInt(text));
					}
					break;
				}
				eventType = mParser.next();
			}
			switch (type) {
			case 0:
				mChatListener.OnChatDataReceived((ChatMessage) udp);
				break;
			case 1:
				mAudioListener.OnAudioChatRequest((AudioRequest) udp);
				break;
			case 2:	
				mVideoListener.OnVideoChatRequest((VideoRequest) udp);
				break;
			default:
				break;
			}
		} catch (XmlPullParserException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
